using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Xml;
using System.Collections.Generic;
using System.Diagnostics;

namespace Dida.Dxml
{
	public class TwoStepXmlConstructorAttribute : Attribute
	{
	}

	public abstract class ParamContainer
	{
	}

	internal class TwoStepXmlConstructorCompilerBuilder
	{
		TypeBuilder typeBuilder;
		MethodBuilder loadParamsMethod;

		public TwoStepXmlConstructorCompilerBuilder(string tagName,
			Type type, ConstructorInfo ctor)
		{
			ParameterInfo[] paramsInfo = ctor.GetParameters();
			Debug.Assert(paramsInfo.Length == 1, "A constructor that has a " +
				"TwoStepXmlConstructor attribute must take a single parameter, of a class (derived from ParamContainer) that contains the data to be loaded from xml");
			Debug.Assert(paramsInfo[0].ParameterType.IsSubclassOf(typeof(ParamContainer)),
				"The parameter of the constructor that was marked with the TwoStepXmlConstructor attribute " + 
				"must be of a type derived from ParamContainer");

			CreateType(tagName);
			CreateLoadParamsMethod(paramsInfo[0].ParameterType);
		}

		private void CreateType(string tagName)
		{
			typeBuilder = SerializationAssembly.CreateType(tagName + "_XmlLoader");
			typeBuilder.SetParent(typeof(XmlObjectCompilerBase));
		}

		private void CreateLoadParamsMethod(Type paramsType)
		{
			loadParamsMethod = typeBuilder.DefineMethod("LoadParams",
				MethodAttributes.Static | MethodAttributes.Public,
				paramsType, new Type[] { typeof(XmlReader) });
			ILGenerator ilGen = loadParamsMethod.GetILGenerator();

			ilGen.Emit(OpCodes.Newobj, paramsType.GetConstructor(Type.EmptyTypes));
			
			foreach (FieldInfo field in paramsType.GetFields())
			{
				ilGen.Emit(OpCodes.Dup);

				DidaXml.Parser parser = DidaXml.GetParser(field.FieldType);
				throw new NotImplementedException();
			}

			foreach (PropertyInfo prop in paramsType.GetProperties())
			{
			}

			ilGen.Emit(OpCodes.Ret);

		}

		public abstract class XmlObjectCompilerBase
		{
		}
	}
}